/**
* \file		Comportement.c
* \brief	Code des fonctions du module Comportement
* \details	C'est ici qu'est le code des accesseurs, mutateurs ainsi que
*		la fonction de test vérifant le bon fonctionnement du module
*		Comportement.
*/

#include "Comportement.h"
#include <assert.h>

/*======================== Gestion de la mémoire =======================*/

void initComp(Comportement *pcomp)
{
   pcomp->premAct = NULL;
   pcomp->dernAct = NULL;
   pcomp->nom = NULL;
   pcomp->techDev = 1;
}

void creerComp(Comportement **pcomp)
{
   *pcomp = (Comportement *)malloc(sizeof(Comportement));
   initComp(*pcomp);
}

void libereComp(Comportement *pcomp)
{
   if(NULL != getNomComp(pcomp))
	{
	   free(pcomp->nom);
	}

   demonteChaineActionComp(pcomp);

   pcomp->nom = NULL;
   setDevComp(pcomp, 0);

}

void detruireComp(Comportement *pcomp)
{
   if(NULL != pcomp)
	{
	   libereComp(pcomp);
	   free(pcomp);
	}
}


/*============================= Accesseurs =============================*/

char *getNomComp(const Comportement *pcomp)
{
   return pcomp->nom;
}

Action *getPremActionComp(const Comportement *pcomp)
{
   return pcomp->premAct;
}

Action *getDernActionComp(const Comportement *pcomp)
{
   return pcomp->dernAct;
}

char getDevComp(const Comportement *pcomp)
{
   return pcomp->techDev;
}


/*============================== Mutateurs =============================*/

void setNomComp(Comportement *pcomp, char *nouvNom)
{
   if(NULL != getNomComp(pcomp))
	{
	   free(pcomp->nom);
	}
   pcomp->nom = (char *)malloc((1+strlen(nouvNom))*sizeof(char));
   strcpy(pcomp->nom, nouvNom);
}

void setPremActionComp(Comportement *pcomp, Action *nouvAct)
{
   pcomp->premAct = nouvAct;
}

void setDernActionComp(Comportement *pcomp, Action *nouvAct)
{
   pcomp->dernAct = nouvAct;
}

void setDevComp(Comportement *pcomp, char nouvVal)
{
   pcomp->techDev = nouvVal;
}


/*=================== (Dé)Montage de la chaine d'actions ===================*/

void ajouteActionComp(Comportement *pcomp, Action *nouvAct)
{
   Action *premAction = getPremActionComp(pcomp);
   Action *dernAction = getDernActionComp(pcomp);

   /* Si la chaîne est vide : le comportement étant une boucle fermée,
   l'action suivant la nouvelle est elle-même, elle est la première et la
   dernière action du comportement */
   if(NULL == premAction)
	{
	   setActionSuivanteAction(nouvAct, premAction);
	   setDernActionComp(pcomp, nouvAct);
	   setPremActionComp(pcomp, nouvAct);
	}

   /* Sinon, l'ancienne première action devient la suivante de la nouvelle
   action, la nouvelle action devient la première action ainsi que la suivante
   de la dernière action */
   else
	{
	   setActionSuivanteAction(nouvAct, premAction);
	   setPremActionComp(pcomp, nouvAct);
	   setActionSuivanteAction(dernAction, nouvAct);
	}
}

void enlevePremActionComp(Comportement *pcomp)
{
   Action *premAction = getPremActionComp(pcomp);
   Action *dernAction = getDernActionComp(pcomp);
   Action *tempAct;

   if(premAction != NULL)
	{
	   /* Si la chaîne n'a qu'une action, on la détruit et on met les
	   pointeurs de tête de chaîne et de fin de chaîne à NULL */
	   if(premAction == dernAction)
		{
		   detruireAction(premAction);
		   setPremActionComp(pcomp, NULL);
		   setDernActionComp(pcomp, NULL);
		}

	   /* Sinon, on récupère l'action suivant la première action. On détruit la première action. Sa suivante devient la première action ainsi que l'action suivante de la dernière action */
	   else
		{
		   tempAct = getActionSuivanteAction(premAction);
		   detruireAction(premAction);
		   setPremActionComp(pcomp, tempAct);
		   setActionSuivanteAction(dernAction, tempAct);
		}
	}
}

void demonteChaineActionComp(Comportement *pcomp)
{
   /* Tant qu'on n'a pas démonté toute la chaîne, on enlève le premier maillon
   */
   while(getPremActionComp(pcomp) != NULL)
	{
	   enlevePremActionComp(pcomp);
	}
}


/*========================== Fonctions autres ==========================*/

char compareNomComp(const Comportement *pcomp, char *nom)
{
   if(0 == strcmp(nom, getNomComp(pcomp)))
	{
	   return 1;
	}
   else
	{
	   return 0;
	}
}

Comportement *creerCompletComp(char *nom)
{
   Comportement *pcomp;
   creerComp(&pcomp);

   setNomComp(pcomp, nom);

   return pcomp;
}

/*========================== Fonction de Test ==========================*/

void testComp()
{
   Comportement *pcomp;
   Action *act1, *act2, *act3;
   int i;
   char mots[][50] = {"Balthazar", "Couper Bois", "Sieste"};
   char val[] = {0,1,3,-8,9,10};

   printf("Test de Comportement\n");
   printf("\tInitialisation d'un Comportement\t\t");

   creerComp(&pcomp);
   assert(NULL == getNomComp(pcomp));
   assert(1 == getDevComp(pcomp));
   assert(NULL == getPremActionComp(pcomp));
   assert(NULL == getDernActionComp(pcomp));
   printf("OK\n");

   printf("\tAffectation et récupération de valeurs\t\t");
   for(i=0; i<3; i++)
	{
	   setNomComp(pcomp, mots[i]);
	   assert(1 == compareNomComp(pcomp, mots[i]));
	}

   for(i=0; i<6; i++)
	{
	   setDevComp(pcomp, val[i]);
	   assert(val[i] == getDevComp(pcomp));
	}

   printf("OK\n");

   printf("\tCreation de la chaîne d'actions\t\t\t");
   creerAction(&act1);
   creerAction(&act2);
   creerAction(&act3);

   ajouteActionComp(pcomp, act1);
   ajouteActionComp(pcomp, act2);
   ajouteActionComp(pcomp, act3);

   printf("OK\n");
   printf("\n");

   detruireComp(pcomp);
}

